package com.chwn.curiousdiary.api;


import com.chwn.curiousdiary.DiaryApplication;
import com.chwn.curiousdiary.utils.StorageUtils;
import com.chwn.harulib.util.NetUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okio.Buffer;
import okio.BufferedSource;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Description:
 * Copyright  : Copyright (c) 2017
 * Company    : chwn
 * Author     : myshikin
 * Date       : 2017-03-20 15:19:46
 */

public class NetWork {
    private static NetWork mInstance;

//    private static final String BASE_URL = "http://192.168.100.53:8080/curiousDiary/";     //测试
//      private static final String BASE_URL = "http://10.10.20.82:8088/curiousDiary/";          //王岩
      private static final String BASE_URL = "http://curiousdiary.mychwn.com/curiousDiary/";       //正式

    /**
     * 有网络的缓存时间  -- 十秒
     */
    private static final int NET_CACHE_TIME = 10;

    /**
     * 无网络缓存时间    -- 7天
     */
    private static final int NONET_CACHE_TIME = 60 * 60 * 24 * 7;

    public static final OkHttpClient mOkHttpClient = new OkHttpClient();

    private NetWork() {
    }

    /**
     * NetWork单例
     * @return
     */
    public static NetWork getInstance() {
        if (mInstance == null) {
            synchronized (NetWork.class) {
                if (mInstance == null) {
                    mInstance = new NetWork();
                }
            }
        }
        return mInstance;
    }

    private IHomeApi   homeApi;
    private ISystemApi systemApi;
    private IUserApi   userApi;

    /**
     * 提供服务
     * @return
     */
    public IHomeApi getHomeApi() {
        return homeApi == null ? getApiService(IHomeApi.class, true) : homeApi;
    }

    /**
     * 提供服务
     * @return
     */
    public <T> T getApiService(Class<T> api) {
        return getApiService(api, false);
    }


    /**
     * 获取服务
     * @param api
     * @param <T>
     * @return
     */
    public <T> T getApiService(Class<T> api, boolean isNeedCache) {
        //        if (retrofit == null) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(configClient(isNeedCache))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        //        }
        return retrofit.create(api);
    }

    /**
     * 设置OkHttpClient的配置
     * @return
     */
    private OkHttpClient configClient(final boolean isNeedCache) {

        File httpCacheDirectory = new File(StorageUtils.getCacheDirectory(DiaryApplication.mInstance, true), "responses");
        int cacheSize = 10 * 1024 * 1024; // 10 MB
        Cache cache = new Cache(httpCacheDirectory, cacheSize);

        OkHttpClient.Builder builder = new OkHttpClient.Builder();

        if (isNeedCache) {
            builder.addInterceptor(CacheInterceptor)
                    .addNetworkInterceptor(logInterceptor)
                    .cache(cache)
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .readTimeout(10, TimeUnit.SECONDS);
        } else {
            builder.addInterceptor(logInterceptor)
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .readTimeout(10, TimeUnit.SECONDS);
        }
        return builder.build();
    }

    /**
     * 日志
     */
    private Interceptor logInterceptor = new Interceptor() {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Response response = null;

            Request request = chain.request();
            response = chain.proceed(request);
            BufferedSource source = response.body().source();
            source.request(Long.MAX_VALUE);
            Buffer buffer = source.buffer();
            Charset UTF8 = Charset.forName("UTF-8");

            //            Logger.e(buffer.clone().readString(UTF8));
            //
            //            Logger.e(request.toString());

            return response;
        }
    };

    /**
     * 缓存
     */
    private Interceptor CacheInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {

            CacheControl.Builder cacheBuilder = new CacheControl.Builder();
            cacheBuilder.maxAge(10, TimeUnit.MINUTES);
            cacheBuilder.maxStale(10, TimeUnit.DAYS);
            CacheControl cacheControl = cacheBuilder.build();

            Request request = chain.request();
            if (!NetUtils.isNetWorkConnectted(DiaryApplication.mInstance)) {
                request = request.newBuilder()
                        .cacheControl(cacheControl)
                        .build();

            }
            Response originalResponse = chain.proceed(request);
            if (NetUtils.isNetWorkConnectted(DiaryApplication.mInstance)) {
                int maxAge = NET_CACHE_TIME;
                return originalResponse.newBuilder()
                        .removeHeader("Pragma")
                        .header("Cache-Control", "public ,max-age=" + maxAge)
                        .build();
            } else {
                int maxStale = NONET_CACHE_TIME;
                return originalResponse.newBuilder()
                        .removeHeader("Pragma")
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                        .build();
            }


        }
    };

    //cache
    Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {

            CacheControl.Builder cacheBuilder = new CacheControl.Builder();
            cacheBuilder.maxAge(60 * 10, TimeUnit.SECONDS);
            cacheBuilder.maxStale(365, TimeUnit.DAYS);
            CacheControl cacheControl = cacheBuilder.build();

            Request request = chain.request();
            if (!NetUtils.isNetWorkConnectted(DiaryApplication.mInstance)) {
                request = request.newBuilder()
                        .cacheControl(cacheControl)
                        .build();

            }
            Response originalResponse = chain.proceed(request);
            if (NetUtils.isNetWorkConnectted(DiaryApplication.mInstance)) {
                int maxAge = 0; // read from cache
                return originalResponse.newBuilder()
                        .removeHeader("Pragma")
                        .header("Cache-Control", "public ,max-age=" + maxAge)
                        .build();
            } else {
                int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
                return originalResponse.newBuilder()
                        .removeHeader("Pragma")
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                        .build();
            }
        }
    };

    /**
     * 为所有请求添加头部 Header 配置的拦截器
     */
    Interceptor headerInterceptor = new Interceptor() {
        boolean isNeedCache = true;

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request.Builder builder = chain.request().newBuilder();
            builder.addHeader("X-Client-Platform", "Android");
            //                builder.addHeader("X-Client-Version", BuildConfig.VERSION_NAME);
            //                builder.addHeader("X-Client-Build", String.valueOf(BuildConfig.VERSION_CODE));

            builder.removeHeader("Accept");
            if (isNeedCache) {
                builder.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
            } else {
                builder.addHeader("Accept", "application/json");
            }

            Request request = builder.build();

            return chain.proceed(request);
        }
    };
}
